﻿using System;
using System.Collections.Generic;
using System.Text;

namespace CompilerPhase4
{
    public class ReserveTable
    {
        #region FIELDS
        string[] reserveTable;    //natrually indexed to match opcode and index
        #endregion

        public ReserveTable()                                     //Constructor
        {
            reserveTable = new string[16];    //16 indexes for natural indexing
            int temp;  /*used to hold return value of Add(). Since reserveTable
            * uses natural indexing, value does not need to be saved except for 
            * debugging purposes*/
            temp = Add("DIV", 1);      //Divide: Compute op1/op2; result in op3
            temp = Add("MUL", 2);    //Multiply: Compute op1/op2; result in op3
            temp = Add("SUB", 3);    //Subtract: Compute op1-op2; result in op3
            temp = Add("ADD", 4);         //Add: Compute op1+op2; result in op3
            temp = Add("ASSIGN", 5);              //Assign: Assign op1 into op3
            temp = Add("BNZ", 6);       //Branch Not Zero: if op1 !=0, PC = op3
            temp = Add("BNP", 7);  //Branch Not Positive: if op1 <= 0, PC = op3
            temp = Add("BNN", 8);  //Branch Not Negative: if op1 >= 0, PC = op3
            temp = Add("BZ", 9);           //Branch Zero: if op1 == 0, PC = op3
            temp = Add("BP", 10);       //Branch Positive: if op1 > 0, PC = op3
            temp = Add("BN", 11);       //Branch Negative: if op1 < 0, PC = op3
            temp = Add("BR", 12);              //Branch Unconditional: PC = op3
            temp = Add("BINDR", 13);//Branch Unconditional (Indirect): PC = op3
            temp = Add("STOP", 14);                         //Terminate Program
            temp = Add("PRINT", 15); //Write Symbol Table Name and Value of op1
        }
/*-----------------------------------------------------------------------------
         * Add: Private funciton used to build the reserve table. Because     |
         * reserveTable is naturally indexed, the return value serves only to |
         * give the option to verify the input.                               |
 *---------------------------------------------------------------------------*/
        private int Add(string name, int code)
        {
            reserveTable[code] = name;//Index entry to opcode value, store name
            return code;
        }
/*-----------------------------------------------------------------------------
         * LookupName: Tries to find the inputted name. If found, it will     |
         * return the index/opcode where the name is stored. If not found it  |
         * will return -1.                                                    |
 *---------------------------------------------------------------------------*/
        public int LookupName(string name)
        {
            int returnIndex = -1;//Value to return start at -1, change if found
            bool stillLooking = true;                   //False when item found
            int index = 1;   //iteration variable to track which index to check
            while (stillLooking == true)//Symbol not found, not at end of table
            {
                if (reserveTable[index].CompareTo(name) == 0)   //If item found
                {
                    returnIndex = index;        //Set the return value to index
                    stillLooking = false;         //No longer looking for value
                }
                else
                {
                    index++;               //Increment index to check next slot
                    if (index > 16)                   //If end of table reached
                    {
                        stillLooking = false;      //No longer looking for vaue
                    }
                }
            }
            return returnIndex;     //Return index where found, -1 if not found
        }
/*-----------------------------------------------------------------------------
         * LookupCode: Given a code, checks if the given code corresponds to  |
         * a valid index, if so, return the name of the given opcode, esle    |
         * return empty string.                                               |
 *---------------------------------------------------------------------------*/
        public string LookupCode(int code)
        {
            string returnString = "";              //Initialize to empty string
            if (code != 0 || code > 16)  //Check if code relates to valid index
            {
                returnString = reserveTable[code]; //Set string to name of code
            }
            return returnString;                                //Return string
        }
/*-----------------------------------------------------------------------------
         * Display: Prints the reserve table, 3 opcodes to a row over 5 total |
         * rows with headers.                                                 |
 *---------------------------------------------------------------------------*/
        public void Display()
        {
            Console.WriteLine("\nRESERVE TABLE");
            Console.WriteLine("\nOpcode\tLabel\t|\tOpcode\tLabel\t|\t" +
                "Opcode\tLabel");
            Console.WriteLine("----------------------------------------" + 
                "------------------------");
            int i = 1;               //iteration variable to grab table indices
            while (i <= 15)              //While there are still items to print
            {
                Console.WriteLine(i.ToString() + "\t" + reserveTable[i] + 
                    "\t|\t" + (i + 1).ToString() + "\t" + reserveTable[i+1]
                    + "\t|\t" + (i + 2).ToString() + "\t" + reserveTable[i+2]);
                i = i + 3;                 //Increment by 3 for next output row
            }
        }
/*---------------------------------------------------------------------------*/
    }
}
